package threadService

import (
	"errors"
	"strings"
	"testing"

	"go.mongodb.org/mongo-driver/bson/primitive"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
	"notabug.org/ropemann/imabon/src/entities/thread"
)

type ThreadServiceTestSuite struct {
	suite.Suite
	board    string
	threadId string
}

func (s *ThreadServiceTestSuite) SetupSuite() {
	s.board = "ani"
	s.threadId = "629bc57195be2b80c621320a"

	GetAllThreadsByBoardFunc = func(board string) []thread.Thread {
		return []thread.Thread{}
	}

	GetMostRecentThreadsFunc = func() map[string]thread.Thread {
		return map[string]thread.Thread{}
	}

	GetThreadByIdFunc = func(board, id string) thread.Thread {
		bid, _ := primitive.ObjectIDFromHex(id)
		return thread.Thread{
			ID: &bid,
		}
	}

	CreateThreadFunc = func(board string, thread thread.Thread) (string, error) {
		return thread.ID.String(), nil
	}
}

func (s *ThreadServiceTestSuite) TestGetMostRecentThreads() {
	recent := GetMostRecentThreads()
	assert.Empty(s.T(), recent)
}

func (s *ThreadServiceTestSuite) TestGetAllThreadsByBoard() {
	threads := GetAllThreadsByBoard(s.board)
	assert.Empty(s.T(), threads)
}

func (s *ThreadServiceTestSuite) TestGetAllThreadsByBoardEmpty() {
	threads := GetAllThreadsByBoard("invalid")
	assert.Empty(s.T(), threads)
}

func (s *ThreadServiceTestSuite) TestPersistThreadEmptyTitle() {
	thread := thread.NewThread("", "", "", "")
	res, err := PersistThread(s.board, *thread)
	assert.Empty(s.T(), res)
	assert.NotNil(s.T(), err)
}

func (s *ThreadServiceTestSuite) TestPersistThreadEmptyBody() {
	thread := thread.NewThread("title", "", "", "")
	res, err := PersistThread(s.board, *thread)
	assert.Empty(s.T(), res)
	assert.NotNil(s.T(), err)
}

func (s *ThreadServiceTestSuite) TestPersistThreadEmptyImage() {
	thread := thread.NewThread("title", "", "body", "")
	res, err := PersistThread(s.board, *thread)
	assert.Empty(s.T(), res)
	assert.NotNil(s.T(), err)
}

func (s *ThreadServiceTestSuite) TestPersistThread() {
	thread := thread.NewThread("title", "author", "body", "image")
	res, err := PersistThread(s.board, *thread)
	assert.Nil(s.T(), err)
	assert.Equal(s.T(), res, thread.ID.String())
}

func (s *ThreadServiceTestSuite) TestPersistThreadFail() {
	CreateThreadFunc = func(board string, thread thread.Thread) (string, error) {
		return "", errors.New("test error")
	}

	thread := thread.NewThread("title", "author", "body", "image")
	res, err := PersistThread(s.board, *thread)
	assert.NotNil(s.T(), err)
	assert.Equal(s.T(), res, "")
}

func (s *ThreadServiceTestSuite) TestGetThreadById() {
	thread := GetThreadById(s.board, s.threadId)
	b, _ := thread.ID.MarshalJSON()
	threadId := strings.ReplaceAll(string(b), "\"", "")
	assert.Equal(s.T(), s.threadId, threadId)
}

func TestThreadServiceTestSuite(t *testing.T) {
	suite.Run(t, new(ThreadServiceTestSuite))
}
